﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using MiniFox.Components;

namespace MiniFox.Data.EntityFramework
{
    /// <summary>
    /// 数据访问提供者(更新到 EF 7.0)
    /// </summary>
    /// <typeparam name="D">EF 上下文对象，继承自 Microsoft.EntityFrameworkCore.DbContext 类型</typeparam>
    [NonSingleTon]
    public abstract class EntityDataProvider<D> : DataProviderBase where D : DbContext
    {
        [AutoDispose]
        private D _dbContext;


        #region constructor

        /// <summary>
        /// 默认使用DbContext对象包含的连接名称构建数据提供者
        /// </summary>
        protected EntityDataProvider()
        { }
        #endregion
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected virtual D CreateDbContext()
        {
            var dbContextType = typeof(D);
            var optionsType = typeof(DbContextOptions<D>);//.MakeGenericType(dbContextType);
            var options = Activator.CreateInstance(optionsType);
            var context = Activator.CreateInstance(dbContextType, options) as D;
            return context;
        }
        /// <summary>
        /// 当前 EF 上下文对象
        /// </summary>
        protected virtual D CurrentDbContext
        {
            get
            {
                return _dbContext ??= CreateDbContext();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        protected DatabaseFacade CurrentDatabase
        {
            get { return this.CurrentDbContext.Database; }
        }
        /// <summary>
        /// 获取当前连接字符串
        /// </summary>
        protected internal string ConnectionString
        {
            get
            {
                return CurrentDatabase.GetConnectionString();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="batchItems"></param>
        /// <returns></returns>
        public int CommitBatch(IEnumerable<BatchOperationItem> batchItems)
        {
            return this.CommitBatch(batchItems.ToArray());
        }
        /// <summary>
        /// 提交批量处理
        /// </summary>
        /// <param name="batchItems">操作对象</param>
        /// <returns></returns>
        public int CommitBatch(params BatchOperationItem[] batchItems)
        {
            if (batchItems == null || batchItems.Length <= 0)
                return 0;
            object[] data = new object[batchItems.Length];
            int i = 0;
            foreach (BatchOperationItem op in batchItems)
            {
                object entity = op.Entity;
                CurrentDbContext.Entry(entity).State = op.State;
                data[i++] = entity;
            }


            this.OnDataBatchExecuting(data);
            int rowcount = this.CurrentDbContext.SaveChanges();
            this.OnDataBatchExecuted((rowcount > 0), data);
            return rowcount;
        }

        #region Insert、Update、Delete

        #region 添加
        /// <summary>
        /// 添加实体到数据库
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="entities"></param>
        /// <returns></returns>
        public override int Insert<TEntity>(params TEntity[] entities)
        {
            return Insert(entities);
        }
        /// <summary>
        /// 添加实体到数据库
        /// </summary>
        /// <param name="entities">要添加的实体,可为多个实体</param>
        public virtual int Insert(params object[] entities)
        {
            CurrentDbContext.AddRange(entities);
            this.OnDataInserting(entities);
            int rowcount = CurrentDbContext.SaveChanges();
            this.OnDataInserted((rowcount > 0), entities);
            return rowcount;
        }

        #endregion

        #region 修改
        /// <summary>
        /// 更新实体到数据库
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="entities"></param>
        /// <returns></returns>
        public override int Update<TEntity>(params TEntity[] entities)
        {
            return Update(entities);
        }
        /// <summary>
        /// 更新实体到数据库
        /// </summary>
        /// <param name="entities"></param>
        public virtual int Update(params object[] entities)
        {
            this.CurrentDbContext.UpdateRange(entities);
            this.OnDataUpdating(entities);
            int rowcount = CurrentDbContext.SaveChanges();
            this.OnDataUpdated((rowcount > 0), entities);
            return rowcount;
        }
        #endregion

        #region 删除
        /// <summary>
        /// 从数据库删除实体
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="entities"></param>
        /// <returns></returns>
        public override int Delete<TEntity>(params TEntity[] entities)
        {
            return Delete(entities);
        }
        /// <summary>
        /// 从数据库删除实体
        /// </summary>
        /// <param name="entities"></param>
        public virtual int Delete(params object[] entities)
        {
            CurrentDbContext.RemoveRange(entities);
            this.OnDataDeleting(entities);
            int rowcount = CurrentDbContext.SaveChanges();
            this.OnDataDeleted((rowcount > 0), entities);
            return rowcount;
        }
        #endregion

        #endregion

        #region 获取查询命令对象
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <returns></returns>
        public override IDataQuery<TEntity> GetDataQuery<TEntity>()
        {
            IDataQuery<TEntity> query = new EntityDataQuery<TEntity>(this.CurrentDbContext);
            return query;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <returns></returns>
        public override IObjectQuery<TEntity> GetObjectQuery<TEntity>()
        {
            IObjectQuery<TEntity> query = new EntityObjectQuery<TEntity>(this.CurrentDbContext);
            return query;
        }
        #endregion

    }

}
